
#include "uds_service.h"
#include "uds_tp.h"
#include "service_cfg.h"
#include "SID10_SessionControl.h"
#include "SID27_SecurityAccess.h"



// UDS 应用层相关定时计数器
static uint32_t uds_timer[UDS_TIMER_CNT] = {0};

extern uint8_t uds_fsa_cnt;

// 肯定响应抑制标志，在收到的服务中若带有子功能，其子功能的最高位 bit7 表示肯定响应抑制位
// 当其置 1 时，则表示不需要回复肯定响应，只进行服务处理即可
static bool_t ssp_flg;

// 服务配置表
extern const uds_service_t uds_service_list[SID_NUM];



/**
 * uds_timer_start - start uds timer
 *
 * void :
 *
 * returns:
 *     void
 */
void uds_timer_start (uint8_t num)
{
	if (num >= UDS_TIMER_CNT) return;

	if (num == UDS_TIMER_FSA)
        uds_timer[UDS_TIMER_FSA] = TIMEOUT_FSA;
	if (num == UDS_TIMER_S3server)
	    uds_timer[UDS_TIMER_S3server] = TIMEOUT_S3server;
}


static void
uds_timer_stop (uint8_t num)
{
	if (num >= UDS_TIMER_CNT) return;

    uds_timer[num] = 0;
}

/**
 * uds_timer_run - run a uds timer, should be invoked per 1ms
 *
 * void :
 *
 * returns:
 *     0 - timer is not running, 1 - timer is running, -1 - a timeout occur
 */
static int
uds_timer_run (uint8_t num)
{
	if (num >= UDS_TIMER_CNT) return 0;

    if (uds_timer[num] == 0)
	{
        return 0;
	}
	else if (uds_timer[num] == 1)
	{
		uds_timer[num] = 0;
	    return -1;
	}
	else
	{
	    /* if (uds_timer[num] > 1) */
		uds_timer[num]--;
	    return 1;
	}

}

/**
 * uds_timer_chk - check a uds timer and stop it
 *
 * num :
 *
 * returns:
 *     0 - timer is not running, 1 - timer is running,
 */
int uds_timer_chk (uint8_t num)
{
	if (num >= UDS_TIMER_CNT) return 0;

	if (uds_timer[num] > 0)
	    return 1;
	else
		return 0;
}

/**
 * uds_no_response - uds response nothing
 *
 * @void :
 *
 * returns:
 *
 */
static void uds_no_response (void)
{
	return;
}
/**
 * uds_negative_rsp - uds negative response
 *
 * @sid :
 * @rsp_nrc :
 *
 * returns:
 *     0 - ok, other - wrong
 */
void uds_negative_rsp (uint8_t sid, uint8_t rsp_nrc)
{
	uint8_t temp_buf[8] = {0};

    if (rsp_nrc != NRC_SERVICE_BUSY)
        uds_timer_start (UDS_TIMER_S3server);

    if (g_tatype == N_TATYPE_FUNCTIONAL)
	{
		if (rsp_nrc == NRC_SERVICE_NOT_SUPPORTED ||
		    rsp_nrc == NRC_SUBFUNCTION_NOT_SUPPORTED ||
			rsp_nrc == NRC_REQUEST_OUT_OF_RANGE)
		    return;
	}
	temp_buf[0] = NEGATIVE_RSP;
	temp_buf[1] = sid;
	temp_buf[2] = rsp_nrc;
	network_send_udsmsg (temp_buf, 3);
	return;
}

/**
 * uds_negative_rsp - uds positive response
 *
 * @data :
 * @len  :
 *
 * returns:
 *     0 - ok, other - wrong
 */
void uds_positive_rsp(uint8_t* data, uint16_t len)
{
	// 启动 S3server 定时器
	uds_timer_start (UDS_TIMER_S3server);
	
	// 肯定响应抑制标志，在收到的服务中若带有子功能，其子功能的最高位 bit7 表示肯定响应抑制位
	// 当其置 1 时，则表示不需要回复肯定响应
	if (ssp_flg == TRUE) return;

	// 调用网络层提供的数据发送接口将数据发送出去
	network_send_udsmsg(data, len);
    return;
}



/******************************************************************************
* 函数名称: static void uds_dataff_indication (uint16_t msg_dlc)
* 功能说明: 首帧指示服务处理
* 输入参数: n_result_t n_result			--处理结果
* 输出参数: 无
* 函数返回: 无
* 其它说明: TP 层接收到首帧后将会调用该函数
******************************************************************************/
static void uds_dataff_indication (n_result_t n_result)
{
	(void)n_result;
	// 关闭 S3server 定时器
	uds_timer_stop(UDS_TIMER_S3server);
}


/******************************************************************************
* 函数名称: static void uds_data_confirm(n_result_t n_result)
* 功能说明: 确认服务处理
* 输入参数: n_result_t n_result		--处理结果
* 输出参数: 无
* 函数返回: 无
* 其它说明: TP 层接收到错误帧或者一些异常超时时将会调用该函数
******************************************************************************/
static void uds_data_confirm(n_result_t n_result)
{
	(void)n_result;
	// 启动 S3server 定时器
	uds_timer_start(UDS_TIMER_S3server);
}


/******************************************************************************
* 函数名称: static void uds_data_indication (uint8_t* msg_buf, uint16_t msg_dlc, n_result_t n_result)
* 功能说明: 指示服务处理
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 在 n_result == N_OK 的情况下，TP 层通过调用该函数将一包完整的有效数据传递过来
******************************************************************************/
static void uds_data_indication (uint8_t* msg_buf, uint16_t msg_dlc, n_result_t n_result)
{
	uint8_t i;
	uint8_t sid;
	uint8_t ssp;

	// 关闭 S3server 定时器
	uds_timer_stop(UDS_TIMER_S3server);

	// 如果 TP 接收到的帧数据异常，则重启 S3server 定时器并退出
    if (n_result != N_OK)
	{
		uds_timer_start(UDS_TIMER_S3server);
	    return;
	}

	// 第一个字节区作为标识区分不同的服务
    sid = msg_buf[0];
	
	// 肯定响应抑制位，在收到的服务中若带有子功能，其子功能的最高位 bit7 表示肯定响应抑制位
	// 当其置 1 时，则表示不需要回复肯定响应，只执行即可
	ssp = UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(msg_buf[1]);

    for (i = 0; i < SID_NUM; i++)
	{
		if(sid != uds_service_list[i].uds_sid)
			continue;

		// 检查是否支持功能寻址
		if(N_TATYPE_FUNCTIONAL == g_tatype && FALSE == uds_service_list[i].fun_spt)
		{
			uds_no_response();
			return;
		}

		// 检查会话状态是否支持
		if((UDS_SESSION_STD == get_current_session() && FALSE == uds_service_list[i].std_spt)
		    || (UDS_SESSION_PROG == get_current_session() && FALSE == uds_service_list[i].prog_spt)
			|| (UDS_SESSION_EXT == get_current_session() && FALSE == uds_service_list[i].ext_spt))
		{
			uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION);
			return;
		}

		// 检查安全访问等级
		if(get_current_sa_lv() < uds_service_list[i].uds_sa)
		{
			uds_negative_rsp(sid, NRC_SECURITY_ACCESS_DENIED);
			return;
		}

		// 检查数据长度是否合法
		if(FALSE == uds_service_list[i].check_len(msg_buf, msg_dlc))
		{
			uds_negative_rsp(sid, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
			return;
		}

		// 肯定响应抑制标志，在收到的服务中若带有子功能，其子功能的最高位 bit7 表示肯定响应抑制位
		// 当其置 1 时，则表示不需要回复肯定响应，只进行服务处理即可
		if (uds_service_list[i].ssp_spt == TRUE && ssp == 0x01)
			ssp_flg = TRUE;
		else
			ssp_flg = FALSE;

		// 执行服务处理函数
		uds_service_list[i].uds_service(msg_buf, msg_dlc);
		
		return;
	}

	// 程序运行到这里说明没找到对应的服务 ID
	uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED);
}


/******************************************************************************
* 函数名称: void service_task(void)
* 功能说明: 应用层任务处理
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 该函数需要被 1ms 周期调用
******************************************************************************/
void service_task(void)
{
	if (uds_timer_run(UDS_TIMER_S3server) < 0)
	{
		// S3server 定时器超时，复位当前会话状态和安全访问等级
		set_current_session(UDS_SESSION_STD);
		set_current_sa_lv(UDS_SA_NON);
	}

	if (uds_timer_run (UDS_TIMER_FSA) < 0)
	{
        uds_fsa_cnt = 0;
	}
}


/******************************************************************************
* 函数名称: int service_init(void)
* 功能说明: 初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: 0: OK; -1: ERR
* 其它说明: 向 TP 层注册一些接口函数
******************************************************************************/
int service_init(void)
{
    nt_usdata_t usdata = {0};

    usdata.ffindication = uds_dataff_indication;
    usdata.indication = uds_data_indication;
    usdata.confirm = uds_data_confirm;

    return network_reg(&usdata);
}

/****************EOF****************/
